package com.zch.application;

import java.util.Arrays;
/*
    基本数据类型(长度不受操作系统的影响以保证Java程序的可移植性)：
    byte(-128~127)占1个字节，short(-32768~32767)占2个字节，int占4个字节，long占8个字节，float占4个字节，double占8个字节
    char(存放单个字符'a')占2个字节，boolean(存放true，false)至少占1个字节(可能是4个字节)

    引用数据类型：
    类(class)，接口(interface)，数组([])
 */

/*
    1.自动类型转换：低到高
    有多种类型的数据混合运算时，系统先自动将所有数据转换成精度最大的那种数据类型，然后再进行计算
    (byte,short)和char之间不会相互自动转换，但当三者进行计算时，会转换为int类型
    2.强制类型转换：高到低
    byte->short->int->long->float->double
    char->int->long->float->double
    强制类型转换需注意溢出或精度损失(浮点型转整型向零取整)
    boolean类型不能进行类型转换
    复合赋值运算符会进行类型转换
    byte b = 2;
    b += 2(b = (byte)(b + 2));
    b++(b = (byte)(b + 1));
 */

/*
    &&(短路与):当左边为false时右边不会执行
    ||(短路或):当左边为true时右边不会执行
    短路运算符（&& 和 ||）能够提升代码的执行效率，避免不必要的计算和副作用
    非短路运算符（& 和 |）则常用于位运算，或在需要强制计算两侧表达式时使用
 */
@SuppressWarnings({"all"})
public class Application {
//public表示这个类是公共的,可以被其他包中的类访问,类名必须与文件名相同.
    public static void main(String[] args) {
        int i = 1;
        i = i++; //(1)temp=i (2)i=i+1 (3)i=temp
        System.out.println(i); //结果为1

        int j = 1;
        j = ++j; //(1)j=j+1 (2)temp=j (3)j=temp
        System.out.println(j); //结果为2

        System.out.println("=======================");
        char d = 'b';
        switch(d) {
            case 'a' :
                System.out.println("ok1");
                break;
            case 'b' :
                System.out.println("ok2");
                break;
            default:
                System.out.println("ok3");
        }
        /*
            switch表达式类型必须与case后的常量类型一致或是可以自动转成可以相互比较的类型
            switch表达式的返回值必须是:(byte,short,char,int,enum,String)
            case子句中的值必须为常量或常量表达式
            default子句是可选的，当没有匹配的case时，执行default
            break语句用来在执行完一个case分支后使程序跳出switch语句块
            如果没有break语句，程序会顺序执行到switch结尾
         */

        System.out.println("=======================");
        System.out.println("com.zch.application.Hello\tWorld!");
        System.out.println("北京欢迎你\r潮州");

        System.out.println("=======================");
        System.out.println("c"+"h");
        /*
            1、当加号两边都是数字或者是数字和字符的时候，这时候的+号做的是加法运算
            2、当加号两边其中是字符串的时候，做的是字符串拼接，拼接后是一个新的字符串
            3、字符串与任何数值做加法，做的是字符串拼接，拼接后是一个新的字符串
        */
        System.out.println("=======================");
        short a = (short) 32768;
        System.out.println(a);

        System.out.println("=======================");
        float b1 = 2323232323232323232323f; //溢出
        float b2 = b1 + 1;
        System.out.println(b1 == b2);

        System.out.println("=======================");
        float b3 = 0.1f;
        double g = 1.0/10; //一个接近0.1的小数，而不是0.1(有小数参与的运算得到的结果是近似值)
        System.out.println(b3 == g);

        System.out.println("=======================");
        int c = 2;
        System.out.println(c << 3); //符号位不变，低位补0
        System.out.println(c >> 3); //低位溢出，符号位不变，并用符号位补齐溢出的高位

        System.out.println("=======================");
        long e = 10_0000_0000L; //long类型需要在数字后加大写L
        boolean f = true;
        System.out.println(f);

        System.out.println("=======================");
        System.out.println(10 / 4); //结果为2
        System.out.println(10.0 / 4); //结果为2.5
        System.out.println(10 % -3); //结果为1
        //a % b = a - a / b * b = a - (int)a / b * b

        System.out.println("=======================");
        Person person3 = new Person("Mary", 18, '女');
        int[] arrays = new int[]{1, 2, 3, 4, 5};
        System.out.println(person3.toString()); //调用重写的toString方法
        System.out.println(arrays); //当直接输出对象时，toString方法会被默认调用
        System.out.println(arrays.toString()); //[I@1eb44e46 [一维数组 I整型 @ 1eb44e46对象的十六进制hashcode
        System.out.println(arrays.hashCode()); //1eb44e46的十进制表示
        /*
            hashcode()：
            提高具有哈希结构的容器的效率
            哈希值是根据地址来的，但不能完全将哈希值等价于地址
         */
        System.out.println(person3.getClass()); //返回运行时类

        System.out.println("=======================");
        int[][] a2 = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
        Hello.print2Arrays(a2);

        System.out.println("=======================");
        for (int[] x: a2) {
            for (int y: x) {
                System.out.print(y + "\t");
            }
            System.out.println();
        }

        System.out.println("=======================");
        Hello.printMultiplication(); //静态方法用类名去调用

        System.out.println("=======================");
        System.out.println(new Person().name); //匿名内部类，使用一次后就消失
        Person per = new Person("jack", 200, '男');
        per.showInfo();

        System.out.println("=======================");
        Student student = new Student();
        Person person = student;
        Object object = person;
        System.out.println(person == student);
        System.out.println(person == object);

        System.out.println("=======================");
        Integer integer1 = new Integer(1000);
        Integer integer2 = new Integer(1000);
        System.out.println(integer1 == integer2); //引用类型比较地址
        System.out.println(integer1.equals(integer2)); //比较整数是否相等

        String str1 = new String("abc");
        String str2 = new String("abc");
        System.out.println(str1 == str2); //引用类型比较地址
        System.out.println(str1.equals(str2)); //比较字符串是否相等

        System.out.println("=======================");
        Person person1 = new Person("tom", 10, '男');
        Person person2 = new Person("tom", 10, '男');
        System.out.println(person1.equals(person2)); //调用重写的equals方法

        System.out.println("=======================");
        Student student1 = new Student();
        student1 = null;
        /*
            这是student1对象就是一个垃圾，垃圾回收器就会回收对象，在销毁对象前，会调用该对象的finalize方法
            程序员就可以在finalize中写自己的业务逻辑代码(比如释放资源：数据库连接，或者打开文件...)
            如果程序员不重写finalize，那么就会调用Object类的finalize，即默认处理
            如果程序员重写了finalize，就可以实现自己的逻辑
        */

        System.out.println("=======================");
        Person person4 = new Person("Mary", 18, '女');
        person4.join();
        Person.count++;
        Person person5 = new Person("Amy", 20, '女');
        person5.join();
        Person.count++;
        System.out.println("共有" + Person.count + "人加入");

        System.out.println("=======================");
        try {
            test(1,0);
        } catch (Error error){
            System.out.println("Error");
        } catch (Exception exception) {
            System.out.println("Exception");;
        } catch (Throwable throwable){
            System.out.println("Throwable");
        }finally { //善后工作，比如关闭IO流，可以不要
            System.out.println("finally");
        }
    }

    //假设方法中处理不了异常，方法上抛出异常
    public static void test(int a, int b) throws ArithmeticException{
        if(b == 0){
            throw new ArithmeticException();
        }
        System.out.println(a / b);
    }
}

//一个源文件中最多只能有一个public类，其他类的个数不限。
//如果源文件包含一个public类，则文件名必需按该类名命名！
class Dog{
    String name;
    int age;
    /*
        如果程序员没有定义构造器，系统会自动生成一个默认的无参构造器，如Dog() {};
        一旦定义了自己的构造器，默认构造器就会被覆盖，除非显式定义一下
     */
    Dog() {
        this("旺财", 3); //只能在构造器中访问另外一个构造器，且必须放在第一条语句
        System.out.println("Dog无参构造调用");
    }

    Dog(String name, int age) {
        System.out.println("Dog有参构造调用");
    }
}

class Cat{
    //变量在不同作用域可以重名
    char d = '中';
}